package models

import (
	"errors"
	"strconv"
)

type SystemKnowledge struct {
	Id          int       `json:"id" xorm:"not null pk autoincr comment('主键') INT(11)"`
	Parentid         int       `json:"parentId" xorm:"not null  comment('父阶段id') INT(11)"`
	Name        string    `json:"name" xorm:"not null comment('题目来源名称') VARCHAR(100)"`
	SubjectId        int    `json:"subjectId" xorm:"not null comment('学科主键') INT(11)"`
	Comment        string    `json:"comment" xorm:"not null comment('题目来源名称') VARCHAR(100)"`
}
var systemknowledge = "system_knowledge"

//返回到客户端的内容


type KnowledgeFlatLevelInfo struct {
	Id          int
	Name        string
	Parentid	int
	LevelIds		string  //把阶段信息拍平了，用逗号隔开
}

func(s *SystemKnowledge) GetRow() bool {
	has, err := mEngine.Get(s)
	if err==nil &&  has  {
		return true
	}
	return false
}
func  (s *SystemKnowledge)GetBySubjectAndLevel(subjectId int,levelIds string)([]KnowledgeFlatLevelInfo,error){

	type KnowledgeInfo struct {
		Id          int  `xorm:"not null pk autoincr comment('主键') INT(11)"`
		Parentid	int	` xorm:"not null  comment('父阶段id') INT(11)"`
		Name        string `xorm:"not null comment('题目来源名称') VARCHAR(100)"`
		LevelId		int ` xorm:"not null  comment('阶段id') INT(11)"`
	}
	var knowledgeinfos []KnowledgeInfo
	var knowledgeFlatLevelInfos  []KnowledgeFlatLevelInfo

	//key值是从数据库得到的knowledge表的id，value 是它在knowledgeFlatLevelInfo的index
	var idIndexMap = make(map[int]int, 0)
	strLevelIds:="("+levelIds+")"
	err := mEngine.Table(systemknowledgelevel).Cols( systemknowledge+".id",systemknowledge+".parentid",systemknowledge+".name",systemknowledgelevel+".level_id").
		Join("INNER", systemknowledge, systemknowledgelevel+".knowledge_id= "+systemknowledge+".id").
		Where(systemknowledge+".subject_id = ?", subjectId).
		Where(systemknowledgelevel+".level_id in  " + strLevelIds).
		Find(&knowledgeinfos)
	if err!=nil{
		return knowledgeFlatLevelInfos,err
	}

	for _,knowledgeInfo := range knowledgeinfos {
		if _,ok := idIndexMap[knowledgeInfo.Id]; ok {
			//如果已经存在
			index:=idIndexMap[knowledgeInfo.Id]
			knowledgeFlatLevelInfos[index].LevelIds=knowledgeFlatLevelInfos[index].LevelIds +","+strconv.Itoa(knowledgeInfo.LevelId)
		}else{
			var kFlatLevelInfo=KnowledgeFlatLevelInfo{}
			kFlatLevelInfo.Id=knowledgeInfo.Id
			kFlatLevelInfo.Parentid=knowledgeInfo.Parentid
			kFlatLevelInfo.Name=knowledgeInfo.Name
			kFlatLevelInfo.LevelIds=strconv.Itoa(knowledgeInfo.LevelId)
			knowledgeFlatLevelInfos=append(knowledgeFlatLevelInfos,kFlatLevelInfo)
			idIndexMap[kFlatLevelInfo.Id]=len(knowledgeFlatLevelInfos)-1
		}


	}
	return knowledgeFlatLevelInfos,err
}

func (k *SystemKnowledge) Add(levelIdsArr[] int) (int,error){
	session := mEngine.NewSession()
	defer session.Close()
	// add Begin() before any action
	if err := session.Begin(); err != nil {
		// if returned then will rodefer session.Close()llback automatically
		return 0,err
	}
	//var uid int64
	_,err:=session.Insert(k)
	if err!=nil {
		return 0,err
	}
	//寻找该节点的所有parent,如果他们没有相应的阶段ID对应，那么也加上
	var parentIds []int
	currentParentId:=k.Parentid
	for ; ; {
		if currentParentId==0 {
			break
		} else{
			parentIds=append(parentIds,currentParentId)
			parentNode,err:=k.GetById(currentParentId)
			if err!=nil{
				return 0,err
			}
			currentParentId=parentNode.Parentid
		}
	}



	for _,levelId:=range levelIdsArr {
		levelModel := SystemLevel{}
		levelModel.Id = levelId
		has := levelModel.GetRow()
		if !has {
			//如果阶段不存在，忽略
			continue
		}

		knowledgeLevelModel := SystemKnowledgeLevel{KnowledgeId: k.Id, LevelId: levelId}

		has, err := session.Get(&knowledgeLevelModel)
		if err != nil {
			return 0, err
		}
		//如果知识点阶段不存在，添加知识点阶段
		if !has {
			_, err = session.Insert(&knowledgeLevelModel)
			if err != nil {
				return 0, err
			}
		}

		//如果这个节点的父节点不包含这些阶段，也要加上
		for _,parentId := range parentIds {
			knowledgeLevelModel := SystemKnowledgeLevel{KnowledgeId: parentId, LevelId: levelId}
			has, err := session.Get(&knowledgeLevelModel)
			if err != nil {
				return 0, err
			}
			//如果知识点阶段不存在，添加知识点阶段
			if !has {
				_, err = session.Insert(&knowledgeLevelModel)
				if err != nil {
					return 0, err
				}
			}
		}


	}




	return k.Id,session.Commit()
}

//根据parentId,找到子Id
func (k *SystemKnowledge) getByParentId(parentId int) ([]int,error) {
	var ids []int
	err:=mEngine.Table(systemknowledge).Cols("id").Where("parentid = ?",parentId).Find(&ids)
	return ids,err
}

//根据当前Id,找到所有子Id
func (k *SystemKnowledge) getAllChildIdsById(id int) ([]int,error) {
	//获得直接子节点
	childIDs,err:=k.getByParentId(id)
	if err != nil {
		return  childIDs,err
	}
	//没有子节点了
	var toDeleteChildIDs []int
	toDeleteChildIDs = append(toDeleteChildIDs,id)
	if len(childIDs)==0{

		return toDeleteChildIDs,nil
	}



	for _,childId := range childIDs {
		tIds, err := k.getAllChildIdsById(childId)
		toDeleteChildIDs = append(toDeleteChildIDs,tIds...)
		if err != nil {
			return  toDeleteChildIDs,err
		}
	}
	return  toDeleteChildIDs,nil
}


func  (k *SystemKnowledge) GetById(id int) (SystemKnowledge,error) {

	var systemknowleges []SystemKnowledge
	err:=mEngine.Table(systemknowledge).Where("id = ?",id).Find(&systemknowleges)
	if len(systemknowleges)==0 {
		return SystemKnowledge{},errors.New("不存在该知识点")
	}
	return systemknowleges[0],err
}

func (k *SystemKnowledge) Update(levelIdsArr[] int) (int,error ){
	session := mEngine.NewSession()
	defer session.Close()
	// add Begin() before any action
	//只能更新名称，阶段，以及说明
	if err := session.Begin(); err != nil {
		// if returned then will rodefer session.Close()llback automatically
		return 0,err
	}

	if _, err := mEngine.Exec("update "+systemknowledge+" set name=?,comment=? where id=?",k.Name,k.Comment,k.Id); err != nil {
		return 0,err
	}

	knowledgeLevelModelForDelete := SystemKnowledgeLevel{KnowledgeId: k.Id}

	_,err :=session.Delete(knowledgeLevelModelForDelete)
	if err!=nil{
		return 0,err
	}



//寻找该节点的所有parent,如果他们没有相应的阶段ID对应，那么也加上
	var parentIds []int
	currentId:=k.Id
	for ; ; {
		if currentId==0 {
			break
		} else{
			parentIds=append(parentIds,currentId)
			parentNode,err:=k.GetById(currentId)
			if err!=nil{
				return 0,err
			}
			currentId=parentNode.Parentid
		}
	}

	for _,levelId:=range levelIdsArr {
		levelModel := SystemLevel{}
		levelModel.Id = levelId
		has := levelModel.GetRow()
		if !has {
			//如果阶段不存在，忽略
			continue
		}

		//如果这个节点,以及它的父节点不包含这些阶段，也要加上
		for _,parentId := range parentIds {
			knowledgeLevelModel := SystemKnowledgeLevel{KnowledgeId: parentId, LevelId: levelId}
			has, err := session.Get(&knowledgeLevelModel)
			if err != nil {
				return 0, err
			}
			//如果知识点阶段不存在，添加知识点阶段
			if !has {
				_, err = session.Insert(&knowledgeLevelModel)
				if err != nil {
					return 0, err
				}
			}
		}




	}

	return k.Id,session.Commit()
}


func (k *SystemKnowledge) Delete() error {

	//TODO: 将彻底删除所有相关的试题！
	//删除所有的子knowledge
	session := mEngine.NewSession()
	defer session.Close()
	// add Begin() before any action
	if err := session.Begin(); err != nil {
		// if returned then will rodefer session.Close()llback automatically
		return err
	}
	//先找到所有的子id

	toDeleteIds,err:=k.getAllChildIdsById(k.Id)
	if err!=nil{
		return err
	}
	length:=len(toDeleteIds)
	for i := length-1; i >=0; i-- {
		toDeleteId:=toDeleteIds[i]

		if _, err := mEngine.Exec("delete from "+systemknowledge+" where id=?",toDeleteId); err != nil {
			return err
		}
		//删除孤立的试题
		if _, err :=mEngine.Exec("delete from "+systemquestion+" where not exists (select 1 from "+systemquestionknowledge+" where "+systemquestionknowledge+".question_id ="+systemquestion+".id )"); err != nil {
			return err

		}

		//删除孤立的试卷
		if _, err :=mEngine.Exec("delete from "+userexam+" where not exists (select 1 from "+userexamquestion+" where "+userexamquestion+".exam_id ="+userexam+".id )"); err != nil {
			return err

		}


	}

	return session.Commit()

}
